package cmich.cps.svn.utility.gui;

import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.ParseException;
import java.util.logging.Logger;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileFilter;

import cmich.cps.svn.utility.Settings;
import cmich.cps.svn.utility.UtilitySystem;

/**
 * The Class Prompts.
 *
 * @author Jonathan Kissinger <kissi1j@cmich.edu>
 */
public class Prompts {
	
	/** The frame. */
	private GUIFrame frame;
	
	/** The settings. */
	private Settings settings;
	
	/** The system. */
	private UtilitySystem system;
	
	/** The Constant instance. */
	private final static Prompts instance = new Prompts();
	
	/** The Constant LOGGER. */
	private final static Logger LOGGER = Logger.getLogger(Prompts.class.getName());

	/**
	 * Instantiates a new prompts.
	 */
	private Prompts() {}

	/**
	 * Gets the single instance of Prompts.
	 *
	 * @return single instance of Prompts
	 */
	public static Prompts getInstance() {
		return instance;
	}

	/**
	 * Initializes variables
	 */
	public void init() {
		frame = GUIFrame.getInstance();
		settings = Settings.getInstance();
		system = UtilitySystem.getInstance();
	}

	/**
	 * Sets subversion.
	 *
	 * @return the subversion executable
	 */
	public String setSubversion() {
		message("Subversion executable location not set, click ok to set the location.");
		JFileChooser chooser = new JFileChooser();
		chooser.setCurrentDirectory(settings.getLocalRepoDirectory());
		if(System.getProperty("os.name").contains("Windows")) {
			class svnFilter extends FileFilter {
				@Override
				public boolean accept(File file) {
					if(file.isDirectory() || file.getName().equalsIgnoreCase("svn.exe")) {
						return true;
					}
					return false;
				}
				@Override
				public String getDescription() {
					return "svn.exe";
				}
			}
			chooser.setDialogTitle("Select Location of svnadmin.exe");
			chooser.setFileFilter(new svnFilter());
		}
		else {
			chooser.setDialogTitle("Select Location of svnadmin");
		}

		if(chooser.showOpenDialog(chooser) == JFileChooser.APPROVE_OPTION) {
			File file = chooser.getCurrentDirectory();
			String path = file.getAbsolutePath();
			LOGGER.config("Subversion location set to: " + path);
			return path;
		}
		else {
			LOGGER.info("User didn't specify a directory for subversion.");
			System.exit(0);
			return null;
		}
	}
	
	/**
	 * Initializes login
	 */
	public void login() {
		LoginDialog login = new LoginDialog(frame);
		login.setVisible(true);
	}

	/**
	 * Displays a fatal error prompt and shuts down the program.
	 *
	 * @param msg the message
	 */
	public void fatalError(String msg) {
		int width = 300;
		msg = "<html><body width='" + width + "'><h1>Fatal Error</h1><p>" + msg;
		msg = msg + "<br><br>Click ok to close utility</p></body></html>";
		JOptionPane.showMessageDialog(frame, msg, "Fatal error", JOptionPane.ERROR_MESSAGE);
		System.exit(1);
	}

	/**
	 * Displays a non-fatal error prompt with the option of shutting down the program.
	 *
	 * @param msg the message
	 */
	public void nonFatalError(String msg) {
		int width = 300;
		msg = "<html><body width='" + width + "'><h1>Error</h1><p>" + msg;
		msg = msg + "<br><br>Click ok to continue, cancel to close the utility</p></body></html>";
		int result = JOptionPane.showConfirmDialog(frame, msg, "Error", JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
		if(result==JOptionPane.CANCEL_OPTION) {
			LOGGER.info("User chose to close the program.");
			System.exit(0);
		}
	}

	/**
	 * Gets the repository from user.
	 *
	 * @return the repository's URI
	 */
	public URI getRepoFromUser() {
		String inputValue = JOptionPane.showInputDialog(frame, "Please input the location of a repository:");
		URI repo;
		try {
			repo = new URI(inputValue);
		} catch (URISyntaxException e) {
			LOGGER.fine(e.toString());
			nonFatalError("There was an error with the repository you entered: " + e.toString());
			repo = getRepoFromUser();
		} catch (NullPointerException e) {
			LOGGER.fine("User cancelled adding a repository");
			return null;
		}
		if(repo==null) {
			LOGGER.fine("User cancelled adding a repository");
			return null;
		}
		return repo;
	}

	/**
	 * Select active repository.
	 *
	 * @return the uri
	 */
	public URI selectActiveRepo() {
		Object[] choices = system.getRepositories().toArray();
		Object selectedValue = JOptionPane.showInputDialog(frame, "Select the repository you'd like to work with:", "Input", JOptionPane.INFORMATION_MESSAGE, null, choices, choices[0]);
		return (URI) selectedValue;
	}

	/**
	 * Gets the local repo directory.
	 *
	 * @return the local repo directory
	 */
	public String getLocalRepoDirectory() {
		message("Local directory for repositories not set, click ok to set the directory.");
		JFileChooser chooser = new JFileChooser();
		chooser.setCurrentDirectory(new File("."));
		chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		chooser.setDialogTitle("Select Location of Local directory for repositories");
		if(chooser.showOpenDialog(chooser) == JFileChooser.APPROVE_OPTION) {
			String path = chooser.getSelectedFile().getAbsolutePath();
			LOGGER.config("Local repositories will be stored in: " + path);
			return path;
		}
		else {
			LOGGER.info("User didn't specify a directory for repositories.");
			System.exit(0);
			return null;
		}
	}

	/**
	 * Gets the input.
	 *
	 * @param msg the msg
	 * @return the input
	 */
	public String getInput(String msg) {
		String inputValue = JOptionPane.showInputDialog(frame, msg);
		return inputValue;
	}

	/**
	 * Gets the due date.
	 *
	 * @return the due date
	 */
	public String getDueDate(String defaultValue) {
		String inputValue = JOptionPane.showInputDialog(frame, "Enter a due date for the assignment:\nFormatting example: 2012-07-03 at 12:19:00 PM", defaultValue);
		try {
			if(inputValue==null) {
				return null;
			}
			settings.sdf.parse(inputValue);
			return inputValue;
		} catch (ParseException e) {
			message("The text you entered didn't match the date formatting, click ok to try again.");
			return getDueDate(inputValue);
		}
	}

	/**
	 * Displays a simple message
	 *
	 * @param msg the message
	 */
	public void message(String msg) {
		JOptionPane.showMessageDialog(frame, msg);
	}
	
	/**
	 * Confirmation dialog
	 *
	 * @param msg the message
	 * @return true, if successful
	 */
	public boolean confirm(String msg) {
		int result = JOptionPane.showConfirmDialog(frame, msg, "Confirmation needed", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE);
		if(result==JOptionPane.YES_OPTION) {
			return true;
		}
		return false;
	}

	/**
	 * Gets the file to add.
	 *
	 * @param dir the directory
	 * @return the file to add
	 */
	public File getFileToAdd(File dir) {
		if(dir==null) {
			dir = settings.getLocalRepoDirectory();
		}
		JFileChooser chooser = new JFileChooser();
		chooser.setCurrentDirectory(dir);
		chooser.setDialogTitle("Select File");
		chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
		if(chooser.showOpenDialog(chooser) == JFileChooser.APPROVE_OPTION) {
			File file = chooser.getSelectedFile();
			return file;
		}
		else {
			return null;
		}
	}

	/**
	 * Gets the file to remove.
	 *
	 * @param dir the directory
	 * @return the file to remove
	 */
	public File getFileToRemove(File dir) {
		JFileChooser chooser = new JFileChooser();
		chooser.setCurrentDirectory(dir);
		chooser.setDialogTitle("Select File");
		chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
		if(chooser.showOpenDialog(chooser) == JFileChooser.APPROVE_OPTION) {
			File file = chooser.getSelectedFile();
			return file;
		}
		else {
			return null;
		}
	}
}

